﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using AmiEmuLib.AmigaMachine;

namespace AmiEmuLib.SaveState
{
    /// <summary>
    /// Use for creating states, if you want use differential states. Working pattern:
    /// create root, creat some diff states to root, create key (diff to root), 
    /// create diff states to key, create new key or root. You must load states in save order, no 
    /// backtracking. No tree structure.
    /// </summary>
    public class StatesManager
    {
        /// <summary>
        /// Key state.
        /// </summary>
        public State Key { get; private set; }

        /// <summary>
        /// Root state.
        /// </summary>
        public State Root { get; private set; }

        /// <summary>
        /// Create diff state to key.
        /// </summary>
        /// <param name="a_machine"></param>
        /// <returns></returns>
        public State CreateDiffState(Machine a_machine)
        {
            if (Key == null)
                throw new InvalidOperationException();

            return new State(a_machine, Key, false);
        }

        /// <summary>
        /// Create key state, diff to Prev.
        /// </summary>
        /// <param name="a_machine"></param>
        /// <returns></returns>
        public State CreateKeyState(Machine a_machine)
        {
            if (Root == null)
                throw new InvalidOperationException();

            Key = new State(a_machine, Root, true);

            return Key;
        }

        /// <summary>
        /// Create full key state.
        /// </summary>
        /// <param name="a_machine"></param>
        /// <returns></returns>
        public State CreateRootState(Machine a_machine)
        {
            Root = new State(a_machine, null, true);
            Key = Root;

            return Root;
        }

        /// <summary>
        /// Load state.
        /// </summary>
        /// <param name="a_fileName"></param>
        /// <returns></returns>
        public State LoadState(string a_fileName)
        {
            using (FileStream fs = new FileStream(a_fileName, FileMode.Open))
                return LoadState(fs);
        }

        /// <summary>
        /// Load state.
        /// </summary>
        /// <param name="a_stream"></param>
        /// <returns></returns>
        public State LoadState(Stream a_stream)
        {
            State state = State.LoadFromXml(a_stream, this);

            if (state.Key)
                Key = state;
            if (state.Root)
                Root = state;

            return state;
        }

        /// <summary>
        /// Find state with this ID.
        /// </summary>
        /// <param name="PrevID"></param>
        /// <returns></returns>
        internal State Lookup(int a_id)
        {
            if (Root != null)
                if (Root.ID == a_id)
                    return Root;

            if (Key != null)
                if (Key.ID == a_id)
                    return Key;

            throw new InvalidOperationException();
        }
    }
}
